//#include <math.h>
#include <stdlib.h>
#include "glut.h"
#include "visor3d.h"
#include "punto3d.h"

#ifndef GL_MULTISAMPLE
#define GL_MULTISAMPLE  0x809D
#endif

Visor3d::Visor3d(QWidget *parent) : QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
{
    desactualizado = false;

    camara.setAnguoVision(90);
    camara.setPosicion(0.5, 0.5, 0.5);
    camara.setPuntoMira(0.5, 0.5, 0);
    camara.setVectorArriba(0, 1, 0);
    camara.setProfundidadMinima(0.1);

    escena = NULL;
    herramienta = NULL;

    startTimer(30);
}

Visor3d::~Visor3d()
{
}

void Visor3d::establecerVision2d(double x, double y, double ancho, double alto, bool origenArriba)
{
    camara.setOrigenHorizontalOrto(x);
    camara.setOrigenVerticalOrto(y);
    camara.setAnchoOrto(ancho);
    camara.setAltoOrto(alto);
    camara.setModo(CAMARA_MODO_ORTOGONAL2D);
    desactualizado = true;
}

void Visor3d::timerEvent(QTimerEvent *evento)
{
    if (desactualizado) {
        updateGL();
        desactualizado = false;
    }
}

QSize Visor3d::minimumSizeHint() const
{
    return QSize(50, 50);
}

QSize Visor3d::sizeHint() const
{
    return QSize(400, 400);
}

void Visor3d::actualizar()
{
    desactualizado = true;    
}

void Visor3d::initializeGL()
{
    if (escena != NULL) {
        escena->inicializar(this);
    }   

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_ALPHA);

    // Se activa el modo blend para permitir transparencia en las texturas
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

   	glShadeModel(GL_SMOOTH);							// Enable Smooth Shading
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);				// Black Background
//    qglClearColor(Qt::black);

    //glEnable(GL_CULL_FACE);

    // Se activa el buffer de profundidad
	glClearDepth(1.0f);									// Depth Buffer Setup
	glEnable(GL_DEPTH_TEST);							// Enables Depth Testing
	glDepthFunc(GL_LEQUAL);								// The Type Of Depth Testing To Do
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	// Really Nice Perspective Calculations
}

void Visor3d::paintGL()
{
    camara.aplicar();

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Modo de modelado
    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

    if (escena != NULL) {
        escena->dibujar();
    }

    
    dibujarEjes();
}

void Visor3d::dibujarEjes()
{
    glLoadIdentity();
    glDisable(GL_TEXTURE_2D);
    
    glBegin(GL_LINES);
        // eje x
        glColor3f(1, 0, 0);
        glVertex3f(0, 0, 0);
        glVertex3f(1, 0, 0);

        //glVertex3f(0, 1, 0);
        //glVertex3f(1, 1, 0);

        //glVertex3f(0, 1, 1);
        //glVertex3f(1, 1, 1);

        //glVertex3f(0, 0, 1);
        //glVertex3f(1, 0, 1);


        // eje y
        glColor3f(0, 1, 0); 
        glVertex3f(0, 0, 0);
        glVertex3f(0, 1, 0);

        //glVertex3f(1, 0, 0);
        //glVertex3f(1, 1, 0);

        //glVertex3f(1, 0, 1);
        //glVertex3f(1, 1, 1);

        //glVertex3f(0, 0, 1);
        //glVertex3f(0, 1, 1);

        // eje z
        glColor3f(0, 0, 1);
        glVertex3f(0, 0, 0);
        glVertex3f(0, 0, 1);

        glVertex3f(1, 0, 0);
        glVertex3f(1, 0, 1);
        
        glVertex3f(1, 1, 0);
        glVertex3f(1, 1, 1);

        glVertex3f(0, 1, 0);
        glVertex3f(0, 1, 1);

    glEnd();

}

void Visor3d::resizeGL(int width, int height)
{
    glViewport(0, 0, width, height);
    desactualizado = true;
}

void Visor3d::mousePressEvent(QMouseEvent* evento)
{
    if (herramienta == NULL) {
        return;
    }
    herramienta->procesarEventoPress(evento, this);
}

void Visor3d::mouseReleaseEvent(QMouseEvent* evento)
{
    if (herramienta == NULL) {
        return;
    }
    herramienta->procesarEventoRelease(evento, this);
}

void Visor3d::mouseMoveEvent(QMouseEvent* evento)
{
    if (herramienta == NULL) {
        return;
    }
    herramienta->procesarEventoMove(evento, this);
}

void Visor3d::wheelEvent(QWheelEvent* evento)
{
    if (herramienta == NULL) {
        return;
    }
    herramienta->procesarEventoWheel(evento, this);
}
